package cn.funeralobjects.upms.service.impl;

import cn.funeralobjects.common.jpa.service.CommonCloudCrudJpaService;
import cn.funeralobjects.common.repository.CommonCloudRepository;
import cn.funeralobjects.common.service.annotataion.CommonRollback;
import cn.funeralobjects.common.service.annotataion.CommonService;
import cn.funeralobjects.common.service.exception.DataConflictException;
import cn.funeralobjects.common.service.validate.DataCheck;
import cn.funeralobjects.upms.entity.ECustomPath;
import cn.funeralobjects.upms.entity.ERole;
import cn.funeralobjects.upms.model.CustomPath;
import cn.funeralobjects.upms.repository.ECustomPathRepository;
import cn.funeralobjects.upms.service.CustomPathService;
import cn.funeralobjects.util.Assert;
import cn.funeralobjects.util.NumberUtils;
import cn.funeralobjects.util.annotation.ArgHasLength;
import cn.funeralobjects.util.annotation.ArgNotZero;
import cn.funeralobjects.util.annotation.AssertArg;

import javax.annotation.Resource;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author FuneralObjects
 * Create date: 2020/5/27 4:19 PM
 */
@CommonService
public class CustomPathServiceImpl implements CustomPathService, CommonCloudCrudJpaService<CustomPath, ECustomPath, Integer> {

    @Resource
    private ECustomPathRepository eCustomPathRepository;

    @Override
    public CommonCloudRepository<ECustomPath, Integer> commonCloudRepository() {
        return eCustomPathRepository;
    }

    @AssertArg
    @Override
    public void checkConflict(@AssertArg CustomPath customPath) throws DataConflictException {
        DataCheck.conflictData(this.existsByNameInScope(customPath.getScope(), customPath.getName()), () -> createDataCode("scope-name", customPath.getScope() + "-" + customPath.getName()));
    }

    @Override
    public ECustomPath toEntity(CustomPath customPath) {
        return Optional.ofNullable(customPath)
                .map(modify -> {
                    ECustomPath entity = new ECustomPath();
                    Optional.ofNullable(customPath.getRoleIds())
                            .ifPresent(roleIds -> entity.setRoles(roleIds.stream()
                                    .map(i -> {
                                        ERole role = new ERole();
                                        role.setId(i);
                                        return role;
                                    }).collect(Collectors.toList())));
                    entity.setUrl(customPath.getUrl())
                            .setScope(customPath.getScope())
                            .setCode(customPath.getCode())
                            .setName(customPath.getName());
                    return entity;
                }).orElse(null);
    }

    @AssertArg
    @Override
    public void checkConflict(@AssertArg CustomPath customPath, @ArgNotZero Integer withoutId) throws DataConflictException {
        DataCheck.conflictData(this.existsByNameInScope(customPath.getScope(), customPath.getName(), withoutId), () -> createDataCode("scope-name", customPath.getScope() + "-" + customPath.getName()));
    }

    @Override
    public void copyToEntity(CustomPath sourceModify, ECustomPath targetEntity) {
        targetEntity
                .setUrl(sourceModify.getUrl())
                .setCode(sourceModify.getCode())
                .setName(sourceModify.getName());
    }

    @Override
    public boolean isValid(Integer id) {
        return NumberUtils.notZero(id);
    }

    @Override
    public void validateModify(CustomPath customPath) {
        Assert.argAssert(customPath, "customPath");
    }

    @AssertArg
    @Override
    public boolean existsByNameInScope(@ArgHasLength String scope, @ArgHasLength String name) {
        return this.eCustomPathRepository.existsAllByScopeAndNameAndDelSalt(scope, name, getExistsDelSalt());
    }

    @AssertArg
    @Override
    public boolean existsByNameInScope(@ArgHasLength String scope, @ArgHasLength String name, @ArgNotZero Integer withoutId) {
        return this.eCustomPathRepository.existsAllByScopeAndNameAndIdNotAndDelSalt(scope, name, withoutId, getExistsDelSalt());
    }

    @Override
    public Optional<ECustomPath> findOneByNameInScope(String scope, String name) {
        return eCustomPathRepository.findFirstByScopeAndNameAndDelSalt(scope, name, getExistsDelSalt());
    }

    @CommonRollback
    @AssertArg
    @Override
    public void removeRoleFromCustomPath(@ArgNotZero Integer roleId, @ArgNotZero Integer id) {
        eCustomPathRepository.findById(id).ifPresent(entity -> {
            entity.getRoles().removeIf(eRole -> roleId.equals(eRole.getId()));
        });

    }

    private Integer getExistsDelSalt() {
        return (Integer) eCustomPathRepository.getDefaultExistsDelSalt();
    }
}
